package com.nulldev.util.scripting.ScriptAPI.baseJS.nsb;

import java.io.Reader;

import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.io.IOUtils;
import com.nulldev.util.scripting.ScriptAPI.baseJS.BaseJS;
import com.nulldev.util.scripting.ScriptAPI.baseJS.legacy.lexer.BaseJSEnvironment;
import com.nulldev.util.scripting.ScriptAPI.baseJS.legacy.lexer.BaseJSVariable;

public class BaseJSSE extends AbstractScriptEngine {

	private final BaseJSSEFactory factory;
	private final BaseJS engine;

	public BaseJSSE() {
		this.factory = new BaseJSSEFactory();
		this.engine = new BaseJS();
	}

	private void setupEnvironment(final Bindings bds, final BaseJSEnvironment bs) {
		bds.forEach((name, value) -> {
			if (value instanceof String || value instanceof Number || value instanceof Integer || value instanceof Float || value instanceof Double
					|| value instanceof Long || value instanceof Short) {
				bs.contents.put(name, new BaseJSVariable(name, value));
				return;
			} else {
				JVM.errorln("Unknown baseJS entry: name=" + name + ", value=" + value);
			}
		});
	}

	@Override
	public Object eval(final String script, final ScriptContext context) throws ScriptException {
		final Bindings bds = context.getBindings(ScriptContext.ENGINE_SCOPE);
		final BaseJSEnvironment bs = new BaseJSEnvironment();
		setupEnvironment(bds, bs);
		return this.engine.compile(script, bs).getReturnValue();
	}

	@Override
	public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
		final Bindings bds = context.getBindings(ScriptContext.ENGINE_SCOPE);
		final BaseJSEnvironment bs = new BaseJSEnvironment();
		setupEnvironment(bds, bs);
		return this.engine.compile(IOUtils.readerToString(reader), bs).getReturnValue();
	}

	@Override
	public Bindings createBindings() {
		return new SimpleBindings();
	}

	@Override
	public ScriptEngineFactory getFactory() {
		return this.factory;
	}

	@Override
	public String toString() {
		return "BaseJSSE[factory=" + this.factory + ",hash=" + this.hashCode() + "]";
	}

}
